package de.jmda.mview.typeshape.relation;

import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.util.List;

/**
 * Connection between type shape relation endpoints, i. e. a connection between
 * {@link RelationEndpointHelper#getConnectorPoint()} of {@link
 * #relationEndpointHelperSource} and {@link #relationEndpointHelperTarget}.
 * <p>
 * The relation endpoints are expected to change. {@link #paint(Graphics2D)}
 * will call {@link #update()} to reflect the changes.
 *
 * @author roger.jmda@gmail.com
 */
public abstract class RelationEndpointConnection
{
	protected RelationEndpointHelper relationEndpointHelperSource;
	protected RelationEndpointHelper relationEndpointHelperTarget;
	
	protected abstract List<Line2D> getLines();

	public RelationEndpointConnection(
			RelationEndpointHelper relationEndpointHelperSource,
			RelationEndpointHelper relationEndpointHelperTarget)
			throws IllegalArgumentException
  {
	  super();
	  
	  this.relationEndpointHelperSource = relationEndpointHelperSource;
	  this.relationEndpointHelperTarget = relationEndpointHelperTarget;
	  
	  try
		{
		  update();
		}
		catch (StateInvalidatedException e)
		{
			throw new IllegalArgumentException(e.getMessage());
		}
  }
	
	/**
	 * Override this method to implement specific update behavior.
	 * <p>
	 * Call this method from within overriding methods to build up an {@link
	 * #update()} stack.
	 *
	 * @throws StateInvalidatedException uncatched from call to {@link
	 *                                   #checkStateInvalidated()}
	 */
	protected void update() throws StateInvalidatedException
	{
		checkStateInvalidated();
	}

	/**
	 * Override this method to implement specific check state behavior.
	 * <p>
	 * Call this method from within overriding methods to build up a {@link
	 * #checkStateInvalidated()} stack.
	 *
	 * @throws StateInvalidatedException if actual state of an instance does not
	 *                                   conform to the constraints of its class,
	 *         this implementation throws an exception if either {@link
	 *         #relationEndpointHelperSource} or {@link
	 *         #relationEndpointHelperTarget} is <code>null</code>
	 */
	protected void checkStateInvalidated()
			throws StateInvalidatedException
	{
		if ((relationEndpointHelperSource == null) ||
		    (relationEndpointHelperTarget == null))
		{
			throw new StateInvalidatedException(
					"source and target endpoint helper must not be null\n" +
					"relationEndpointHelperSource == null: " +
					(relationEndpointHelperSource == null) + "\n" +
					"relationEndpointHelperTarget == null: " +
					(relationEndpointHelperTarget == null));
		}
	}
	
	public void paint(Graphics2D graphics2d)
	{
		for (Line2D line : getLines())
		{
			graphics2d.drawLine(
					(int) line.getX1(), (int) line.getY1(),
					(int) line.getX2(), (int) line.getY2());
		}
	}
}